<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模拟交易</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="../js/lightweight-charts.standalone.production.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        #chart-container {
            width: 80%;
            max-width: 1000px;
            height: 600px;
            margin: 20px 0;
            display: flex;
            flex-direction: column;
        }
        .chart-wrapper {
            position: relative;
            width: 100%;
        }
        #chart, #macd-chart {
            width: 100%;
        }
        #chart {
            height: 400px;
        }
        #macd-chart {
            height: 200px;
        }
        .controls {
            display: flex;
            justify-content: center;
            margin: 20px;
        }
        .controls div {
            margin: 0 10px;
        }
        #history {
            width: 80%;
            max-width: 800px;
            margin-top: 20px;
            border: 1px solid #ddd;
            padding: 10px;
            list-style-type: none;
        }
        #history li {
            margin: 5px 0;
        }
        .balance {
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <div id="chart-container">
        <div class="chart-wrapper">
            <div id="chart"></div>
        </div>
        <div class="chart-wrapper">
            <div id="macd-chart"></div>
        </div>
    </div>
    <div class="controls">
        <button onclick="nextKline()">下一根K线</button>
        <button onclick="trade('buy')">买入</button>
        <button onclick="trade('sell')">卖出</button>
        <button onclick="generateRandomKlines()">生成随机K线</button>
    </div>
    <div class="balance">
        <p>余额：<span id="balance">1000000</span> USD</p>
        <p>持仓：<span id="position">0</span> 个</p>
    </div>
    <div>
        <h2>交易历史</h2>
        <ul id="history"></ul>
    </div>
    <script>
        var chartWidth = document.getElementById('chart').clientWidth;
        var chartHeight = 400;
        var macdChartHeight = 200;
        var maxDataPoints = 150;

        var chart = LightweightCharts.createChart(document.getElementById('chart'), {
            width: chartWidth,
            height: chartHeight,
            rightPriceScale: {
                visible: false,
            },
            timeScale: {
                visible: false,
                rightOffset: 10,
            },
            handleScroll: false,
            handleScale: false,
        });

        var candleSeries = chart.addCandlestickSeries();

        var macdChart = LightweightCharts.createChart(document.getElementById('macd-chart'), {
            width: chartWidth,
            height: macdChartHeight,
            rightPriceScale: {
                visible: false,
            },
            timeScale: {
                visible: false,
                rightOffset: 10,
            },
            handleScroll: false,
            handleScale: false,
        });

        var macdLineSeries = macdChart.addLineSeries({
            color: 'blue',
            lineWidth: 1,
        });
        var signalLineSeries = macdChart.addLineSeries({
            color: 'orange',
            lineWidth: 1,
        });
        var histogramSeries = macdChart.addHistogramSeries({
            base: 0,
            priceFormat: {
                type: 'price',
                precision: 2,
                minMove: 0.01,
            },
            style: 2,
        });

        var klinesData = [];
        var macdData = [];
        var signalData = [];
        var histogramData = [];

        var balance = 1000000;
        var position = 0;

        function calculateMACD(data, shortPeriod = 12, longPeriod = 26, signalPeriod = 9) {
            let shortEMA = calculateEMA(data, shortPeriod);
            let longEMA = calculateEMA(data, longPeriod);
            let macdLine = shortEMA.map((short, index) => {
                if (index < longPeriod - 1) {
                    return null;
                }
                return short - longEMA[index];
            }).slice(longPeriod - 1);

            let signalLine = calculateEMA(macdLine, signalPeriod);
            let histogram = macdLine.map((macd, index) => {
                if (index < signalPeriod - 1) {
                    return null;
                }
                return macd - signalLine[index];
            }).slice(signalPeriod - 1);

            let adjustedMacdLine = new Array(longPeriod - 1).fill(null).concat(macdLine);
            let adjustedSignalLine = new Array(longPeriod + signalPeriod - 2).fill(null).concat(signalLine);
            let adjustedHistogram = new Array(longPeriod + signalPeriod - 2).fill(null).concat(histogram);

            return {
                macdLine: adjustedMacdLine,
                signalLine: adjustedSignalLine,
                histogram: adjustedHistogram,
            };
        }

        function calculateEMA(data, period) {
            let multiplier = 2 / (period + 1);
            let emaArray = [];
            data.forEach((item, index) => {
                if (index < period - 1) {
                    emaArray.push(null);
                } else if (index === period - 1) {
                    let sum = 0;
                    for (let i = 0; i < period; i++) {
                        sum += item;
                    }
                    emaArray.push(sum / period);
                } else {
                    emaArray.push((item - emaArray[emaArray.length - 1]) * multiplier + emaArray[emaArray.length - 1]);
                }
            });
            return emaArray;
        }

        function updateMACD() {
            let closePrices = klinesData.map((k) => k.close);
            let { macdLine, signalLine, histogram } = calculateMACD(closePrices);
            macdData = klinesData.map((k, i) => ({ time: k.time, value: macdLine[i] }));
            signalData = klinesData.map((k, i) => ({ time: k.time, value: signalLine[i] }));
            histogramData = klinesData.map((k, i) => ({
                time: k.time,
                value: histogram[i],
                color: histogram[i] >= 0 ? 'green' : 'red',
            }));

            macdLineSeries.setData(macdData);
            signalLineSeries.setData(signalData);
            histogramSeries.setData(histogramData);
        }

        function nextKline() {
            $.post('/next_kline', function (data) {
                if (data.status === 'end') {
                    alert('No more Kline data available');
                } else {
                    var timeOffset =
                        klinesData.length > 0
                            ? klinesData[klinesData.length - 1].time + 1800
                            : Date.parse(data.timestamp) / 1000;
                    var kline = {
                        time: timeOffset,
                        open: parseFloat(data.open),
                        high: parseFloat(data.high),
                        low: parseFloat(data.low),
                        close: parseFloat(data.close),
                    };
                    klinesData.push(kline);
                    if (klinesData.length > maxDataPoints) {
                        klinesData.shift();
                    }
                    candleSeries.setData(klinesData);
                    updateMACD();
                    chart.timeScale().setVisibleRange({
                        from: klinesData[Math.max(0, klinesData.length - maxDataPoints)].time,
                        to: klinesData[klinesData.length - 1].time
                    });
                    macdChart.timeScale().setVisibleRange({
                        from: klinesData[Math.max(0, klinesData.length - maxDataPoints)].time,
                        to: klinesData[klinesData.length - 1].time
                    });
                }
            });
        }

        function trade(action) {
            var currentPrice = klinesData[klinesData.length - 1].close;

            if (action === 'buy') {
                var amount = balance / currentPrice;
                var cost = amount * currentPrice;
                balance -= cost;
                position += amount;
                $('#history').append(
                    '<li>买入 ' +
                        amount.toFixed(2) +
                        ' 个，价格 ' +
                        currentPrice.toFixed(2) +
                        '</li>'
                );
            } else if (action === 'sell') {
                var amount = position;
                balance += amount * currentPrice;
                position -= amount;
                $('#history').append(
                    '<li>卖出 ' +
                        amount.toFixed(2) +
                        ' 个，价格 ' +
                        currentPrice.toFixed(2) +
                        '</li>'
                );
            }

            $('#balance').text(balance.toFixed(2));
            $('#position').text(position.toFixed(2));
        }

        function generateRandomKlines() {
            $.post('/generate_random_klines', function (response) {
                if (response.status === 'success') {
                    alert('刷新随机K线成功');
                    klinesData = [];
                    macdData = [];
                    signalData = [];
                    histogramData = [];
                    balance = 1000000;
                    position = 0;
                    $('#history').empty();
                    $('#balance').text(balance.toFixed(2));
                    $('#position').text(position.toFixed(2));
                    nextKline();
                } else {
                    alert('刷新随机K线失败: ' + response.message);
                }
            });
        }

        $(document).ready(function () {
            nextKline();
        });

        window.addEventListener('resize', () => {
            var newWidth = document.getElementById('chart').clientWidth;
            chart.resize(newWidth, chartHeight);
            macdChart.resize(newWidth, macdChartHeight);
        });
    </script>
</body>
</html>
